'''
Description: 
Author: Zilu
Date: 2021-11-07 23:59:23
Version: 
LastEditTime: 2021-11-08 12:38:01
LastEditors: Zilu
'''

# python 是动态语言，函数和类的定义都是在运行时动态创建的
class Hello(object):
    def hello(self, name = 'world'):
        print('Hello, %s' % name)

h = Hello()
h.hello()
type(Hello)
type(h)

# 上面的Hello是一个type类型，h是一个实例，类型是Hello
# class的定义是运行时动态创建的，创建class的方法就是type()函数
# 使用type创建函数
def fn(self,name='world'):
    print('Hello hello, %s' % name)

Hello = type('Hello',(object,),dict(hello=fn))   # 创建Hello class
h = Hello()
h.hello()
type(Hello)
type(h)

# type创建出的类和class创建出来的一模一样，
# python解释器遇到class，仅仅是扫描一下class的语法，然后用type创建

# type传入的3个参数：
# 1.class的名称
# 2.继承的父类集合，如果只有一个父类，注意单元素tuple的写法
# 3.class的方法名称和函数绑定

# 可以使用元类 metaclass 创建类
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

# 传入 metaclass 参数作为来定制
class MyList(list, metaclass=ListMetaclass):
    pass

# 在解释器创建 MyList 时，通过ListMetaclass.__new__()来创建
# __new__()方法接收到的参数依次是：
# 1. 当前准备创建的类的对象；
# 2. 类的名字；
# 3. 类继承的父类集合；
# 4. 类的方法集合。

L1 = MyList()
L1.add(1)
L1

L2 = list()
L2
# L2.add(1)        # 使用错误

# 简单 ORM 框架
class Field(object):
    def __init__(self, name, column_type) -> None:
        super().__init__()
        self.name = name
        self.column_type = column_type

    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)

class StringField(Field):
    def __init__(self, name) -> None:
        super(StringField, self).__init__(name, 'varchar(100)')

class IntegerField(Field):
    def __init__(self, name) -> None:
        super(IntegerField, self).__init__(name, 'bigint')

class ModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        if name == 'Model':
            return type.__new__(cls, name, bases, attrs)

        print('Found model: %s' % name)
        mappings = dict()
        for k, v in attrs.items():
            if isinstance(v, Field):
                print('Found mapping %s => %s' % (k, v))
                mappings[k] = v
        for k in mappings.keys():
            attrs.pop(k)
        attrs['__mappings__'] = mappings        # 保存属性和列的映射关系
        attrs['__tables__'] = name       # 假设表名和类名一致
        return type.__new__(cls, name, bases, attrs)

class Model(dict, metaclass = ModelMetaclass):
    def __init__(self,**kw):
        super(Model,self).__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Model' object has no attibute '%s'" % key)

    def __setattr__(self, key, value):
        self[key] = value

    def save(self):
        fields = []
        params = []
        args = []
        for k, v in self.__mappings__.items():
            fields.append(v.name)
            params.append('?')
            args.append(getattr(self,k,None))
        sql = 'insert into %s (%s) values (%s)' % (self.__tables__, ','.join(fields), ','.join(params))
        print("SQL: %s" % sql)
        print('ARGS: %s' % str(args))

# metaclass 被隐式地继承到子类 User
class User(Model):
    id = IntegerField('id')
    name = StringField('name')
    email = StringField('email')
    password = StringField('password')

u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()





